// 定义字符串类型的变量
let str: string = "hello";
str = "world";

// ts是有自动类型推断的
let str2 = "hello2";

let str3: string;
str3 = "world2";

// 定义数字类型的变量
let num1: number = 3;
num1 = 4;

// 定义布尔值类型
let done: boolean = true;
done = false;

// 定义undefined类型
let udf: undefined = undefined;
// udf = "r34";

// 定义null类型
let nl: null = null;

// 联合类型
let a: number | string | boolean = 1;
a = "hello";
a = true;

// const b = localStorage.getItem("abc");
// console.log(b && b.split(""));
// if (b) {
//   b.split("")
// }

// any表示任意类型
let c: any = 3;
c = [1, 2, 3];

// 数组类型
let arr1: number[] = [1, 2, 3, 4, 5];
let arr2: Array<string> = ["1", "2", "3"];
let arr3: (number | boolean)[] = [1, 2, true];
let arr4: Array<number | boolean> = [1, 2, true];
let arr5: Array<any> = [1, 2, true];
let arr6: any = [1, 2, true];

// 如果要定义数组，必须是两项，第一项必须是数字，第二项必须是字符串
// 元组类型,特殊的数组
let arr7: [number, string] = [1, "3"];
// arr7[3]
// arr7.split("");

// 对象类型
// 接口 interface, 专门用来定义对象类型的
interface ObjType {
  // 接口的首字母大小，分号
  // 问号表示可选属性
  name: string;
  age: number;
  sex?: number;
  likes: string[];
  // 索引签名
  [propname: string]: any;
}
let obj1: ObjType = {
  name: "pengshao",
  age: 20,
  likes: ["c", "t", "r", "l"],
  a: 1,
  b: 2,
  c: true,
};
obj1.sex = 1;

// 对象的练习
interface ItemType {
  name: string;
  id: number;
  children?: ItemType[];
}
let array: ItemType[] = [
  {
    name: "zhangsan",
    id: 1,
    children: [
      {
        name: "zhangqi",
        id: 3,
      },
      {
        name: "zhangba",
        id: 4,
      },
    ],
  },
  {
    name: "lisi",
    id: 2,
  },
];

// 枚举
// 特殊的对象，可以通过key找到value，也可以通过value找到key
// 我们自己的代码几乎不会出现的
enum Color {
  Red = 5,
  Green = 10,
  Blue = 15,
}
let g: Color = Color.Green;
// console.log(g);
let colorname: string = Color[15];
// console.log(colorname);

// 函数类型
// 函数加的是返回值的类型
// 参数类型必须要加
// 问号表示可选参数
function add(x: number, y?: number): number {
  return y ? x + y : x;
}
add(3);

let add2: (x: number, y: number) => number = function (
  x: number,
  y: number
): number {
  return x + y;
};
add2(3, 4);

// void表示没有返回值,专门给函数用的
function fn(): void {
  console.log(123);
}

// never类型, 表示从不，死循环或者报错
// function fn2(): never {
//   while(true) {}
// }
function fn3(): number | never {
  if (Math.random() > 0.5) {
    return 3;
  } else {
    throw new Error("错误");
  }
}

// 泛型类型(在函数调用的时候传递了类型的变量)
// 特殊的函数
function fn4<T>(x: T, y: T) {
  // return 11;
}
fn4<number>(3, 4);

// const count = ref<number>(3);

// 类
interface ObjType2 {
  name: string;
}
class Animal {
  constructor(obj: ObjType2) {
    this.name = obj.name;
  }
  name: string = "dog";
  sayName(): string {
    return this.name;
  }
}

class Dog extends Animal {
  // constructor构造器
  // 当这个构造函数被实例化的时候调用
  constructor(obj: ObjType2) {
    // super函数调用，就相当于调用父类的constructor
    super(obj);
    // console.log(obj);
  }
}

const dog = new Dog({
  name: "cat",
});

console.log(dog.name);
